package com.pai4j.message.aggregation;

import com.pai4j.message.model.MessageContext;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.function.Predicate;

/**
 * 聚合规则
 * 定义哪些消息可以聚合
 *
 * @author PAI4J Team
 * @date 2025-11-01
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AggregationRule {

    /**
     * 规则名称
     */
    private String ruleName;

    /**
     * 时间窗口（秒）
     */
    @Builder.Default
    private Integer windowSeconds = 300; // 默认5分钟

    /**
     * 最小聚合数量
     */
    @Builder.Default
    private Integer minCount = 2;

    /**
     * 最大聚合数量
     */
    @Builder.Default
    private Integer maxCount = 100;

    /**
     * 是否启用
     */
    @Builder.Default
    private Boolean enabled = true;

    /**
     * 聚合维度
     * 例如：resourceId, receiverId, messageType等
     */
    @Builder.Default
    private String aggregateDimension = "resourceId,receiverId,messageType";

    /**
     * 匹配条件
     */
    private Predicate<MessageContext> matcher;

    /**
     * 判断消息是否匹配规则
     */
    public boolean matches(MessageContext context) {
        if (!enabled) {
            return false;
        }

        if (matcher != null) {
            return matcher.test(context);
        }

        // 默认匹配所有
        return true;
    }

    /**
     * 生成聚合键
     * 用于标识可以聚合在一起的消息
     */
    public String generateAggregationKey(MessageContext context) {
        StringBuilder key = new StringBuilder();
        
        String[] dimensions = aggregateDimension.split(",");
        for (String dimension : dimensions) {
            dimension = dimension.trim();
            
            switch (dimension) {
                case "resourceId":
                    if (context.getResourceInfo() != null) {
                        key.append(context.getResourceInfo().getResourceId()).append(":");
                    }
                    break;
                case "resourceType":
                    if (context.getResourceInfo() != null) {
                        key.append(context.getResourceInfo().getResourceType()).append(":");
                    }
                    break;
                case "receiverId":
                    key.append(context.getReceiverId()).append(":");
                    break;
                case "messageType":
                    if (context.getMessageDTO() != null) {
                        key.append(context.getMessageDTO().getClass().getSimpleName()).append(":");
                    }
                    break;
                default:
                    break;
            }
        }
        
        return key.toString();
    }

    /**
     * 创建默认规则
     */
    public static AggregationRule createDefault() {
        return AggregationRule.builder()
                .ruleName("default")
                .windowSeconds(300)
                .minCount(2)
                .maxCount(100)
                .enabled(true)
                .aggregateDimension("resourceId,receiverId,messageType")
                .build();
    }

    /**
     * 创建点赞聚合规则
     */
    public static AggregationRule createLikeRule() {
        return AggregationRule.builder()
                .ruleName("like")
                .windowSeconds(300)
                .minCount(2)
                .maxCount(100)
                .enabled(true)
                .aggregateDimension("resourceId,receiverId,messageType")
                .matcher(ctx -> ctx.getMessageDTO() != null && 
                        ctx.getMessageDTO().getClass().getSimpleName().contains("Like"))
                .build();
    }

    /**
     * 创建评论聚合规则
     */
    public static AggregationRule createCommentRule() {
        return AggregationRule.builder()
                .ruleName("comment")
                .windowSeconds(600) // 10分钟
                .minCount(3)
                .maxCount(50)
                .enabled(true)
                .aggregateDimension("resourceId,receiverId,messageType")
                .matcher(ctx -> ctx.getMessageDTO() != null && 
                        ctx.getMessageDTO().getClass().getSimpleName().contains("Comment"))
                .build();
    }
}

